/**
 * @file tcpecho.c
 * @author zdk
 * @brief 基于TCP协议的回显服务器，一次只能响应一个连接
 * @version 0.1
 * @date 2021-08-24
 * 
 * @copyright Copyright (c) 2021
 * 
 */

#include "lwip/api.h"
#include "rtthread.h"

/* 设置为1来启用这个demo */
#if 1

/**
 * @brief 回显服务器进程
 * 
 * @param arg 自定义参数
 */
static void tcpecho_thread(void *arg)
{
    struct netconn *conn, *newconn;
    err_t err;

    /* 新建、绑定、监听 */
    conn = netconn_new(NETCONN_TCP);
    netconn_bind(conn, NULL, 7);
    netconn_listen(conn);

    while(1)
    {
        err = netconn_accept(conn, &newconn); /* 等待新连接到来 */
        if(ERR_OK == err)
        {
            struct netbuf *buf;
            void *data;
            u16_t len;

            /* 在新连接上等待，循环接收数据包 */
            while((err = netconn_recv(newconn, &buf)) == ERR_OK)
            {
                do
                {
                    netbuf_data(buf, &data, &len);
                    err = netconn_write(newconn, data, len, NETCONN_COPY);
                } while (netbuf_next(buf) >= 0);
                netbuf_delete(buf);
            }

            /* 发生错误或接收到空包，则需要断开连接 */
            netconn_close(newconn);
            netconn_delete(newconn);
        }
    }
}

/**
 * @brief 初始化服务器线程
 * 
 */
int tcpecho_init(void)
{
    sys_thread_t ret;
    ret = sys_thread_new("tcpecho", tcpecho_thread, NULL, 1024, TCPIP_THREAD_PRIO + 1);
    LWIP_ASSERT(("tcpecho_init failure."), ret);
    return 0;
}
INIT_APP_EXPORT(tcpecho_init);

#endif
